#ifndef _SYS_STR_H_
#define _SYS_STR_H_

#include <stdarg.h>
#include "FanObj.h"
#include "SysTypes.h"

#define STR_VTABLE(self)   ((StrVTable*)((FanObj*)self)->vtable)


extern Type*    Str_classType;
extern VTable*  Str_classVTable;


/* [sys::Str] Attributes */
struct Str
{
  FanObj        super;
  Char*         buffer;
  char*         cStr;
  Int           len;
  Int           hash;
};


/* [sys::Str] Virtual-table */
typedef struct StrVTable
{
  FanObjVTable  super;
} StrVTable;


/* [sys::Str] Methods and fields */
Bool            Str_equals(Obj self, NullableObj obj);
Int             Str_compare(Obj self, Obj obj);
Int             Str_hash(Obj self);
Str*            Str_toStr(Obj self);
Str*            Str_defVal(void);
Str*            Str_fromChars(List* chars);
Bool            Str_equalsIgnoreCase(Str* self, Str* s);
Int             Str_compareIgnoreCase(Str* self, Str* s);
Str*            Str_toLocale(Str* self);
Bool            Str_isEmpty(Str* self);
Int             Str_size(Str* self);
Str*            Str_intern(Str* self);
Bool            Str_startsWith(Str* self, Str* s);
Bool            Str_endsWith(Str* self, Str* s);
NullableInt     Str_index_1(Str* self, Str* s);
NullableInt     Str_index(Str* self, Str* s, Int offset);
NullableInt     Str_indexr_1(Str* self, Str* s);
NullableInt     Str_indexr(Str* self, Str* s, Int offset);
NullableInt     Str_indexIgnoreCase_1(Str* self, Str* s);
NullableInt     Str_indexIgnoreCase(Str* self, Str* s, Int offset);
NullableInt     Str_indexrIgnoreCase_1(Str* self, Str* s);
NullableInt     Str_indexrIgnoreCase(Str* self, Str* s, Int offset);
Bool            Str_contains(Str* self, Str* s);
Bool            Str_containsChar(Str* self, Int ch);
Int             Str_get(Str* self, Int index);
Int             Str_getSafe_1(Str* self, Int index);
Int             Str_getSafe(Str* self, Int index, Int def);
Str*            Str_getRange(Str* self, Range* range);
Str*            Str_plus(Str* self, NullableObj obj);
List*           Str_chars(Str* self);
void            Str_each(Str* self, Func* c);
void            Str_eachr(Str* self, Func* c);
Bool            Str_any(Str* self, Func* c);
Bool            Str_all(Str* self, Func* c);
Str*            Str_spaces(Int n);
Str*            Str_lower(Str* self);
Str*            Str_upper(Str* self);
Str*            Str_capitalize(Str* self);
Str*            Str_decapitalize(Str* self);
Str*            Str_toDisplayName(Str* self);
Str*            Str_fromDisplayName(Str* self);
Str*            Str_justl(Str* self, Int width);
Str*            Str_justr(Str* self, Int width);
Str*            Str_padl_1(Str* self, Int width);
Str*            Str_padl(Str* self, Int width, Int ch);
Str*            Str_padr_1(Str* self, Int width);
Str*            Str_padr(Str* self, Int width, Int ch);
Str*            Str_reverse(Str* self);
Str*            Str_trim(Str* self);
Str*            Str_trimStart(Str* self);
Str*            Str_trimEnd(Str* self);
List*           Str_split_0(Str* self);
List*           Str_split_1(Str* self, NullableInt separator);
List*           Str_split(Str* self, NullableInt separator, Bool trim);
List*           Str_splitLines(Str* self);
Str*            Str_replace(Str* self, Str* from, Str* to);
Int             Str_numNewlines(Str* self);
Bool            Str_isAscii(Str* self);
Bool            Str_isSpace(Str* self);
Bool            Str_isUpper(Str* self);
Bool            Str_isLower(Str* self);
Bool            Str_isAlpha(Str* self);
Bool            Str_isAlphaNum(Str* self);
Int             Str_localeCompare(Str* self, Str* s);
Str*            Str_localeLower(Str* self);
Str*            Str_localeUpper(Str* self);
Str*            Str_localeCapitalize(Str* self);
Str*            Str_localeDecapitalize(Str* self);
NullableBool    Str_toBool_0(Str* self);
NullableBool    Str_toBool(Str* self, Bool checked);
NullableInt     Str_toInt_0(Str* self);
NullableInt     Str_toInt_1(Str* self, Int radix);
NullableInt     Str_toInt(Str* self, Int radix, Bool checked);
NullableFloat   Str_toFloat_0(Str* self);
NullableFloat   Str_toFloat(Str* self, Bool checked);
Decimal*        Str_toDecimal_0(Str* self);
Decimal*        Str_toDecimal(Str* self, Bool checked);
Str*            Str_toCode_0(Str* self);
Str*            Str_toCode_1(Str* self, NullableInt quote);
Str*            Str_toCode(Str* self, NullableInt quote, Bool escapeUnicode);
Str*            Str_toXml(Str* self);
Uri*            Str_toUri(Str* self);
InStream*       Str_in(Str* self);
Buf*            Str_toBuf_0(Str* self);
Buf*            Str_toBuf(Str* self, Charset* charset);


/* [sys::Str] Extra methods */
Str*            Str_newUninitialized(Int len);
Str*            Str_newFromBuffer(Char* buffer, Int len);
Str*            Str_newFromCStr(const char* cStr);
Str*            Str_newWithFormat(const char* format, ...);
Str*            Str_newWithFormatValist(const char* format, va_list args);
const char*     Str_cStr(Str* self);
Bool            Str_fillCStr(Str* self, char* cStr, Int maxLen);
Str*            Str_substr(Str* self, Int start, Int end);
NullableInt     Str_indexChar(Str* self, Int ch);
NullableInt     Str_rindexChar(Str* self, Int ch);


/* [sys::Str] Type-system functions */
Type*           Str_initType(void);
VTable*         Str_initVTable(void);
void            Str_initStatic(void);


#endif
